<?php
declare (strict_types = 1);
namespace come;
use \ArrayAccess;
class Model implements ArrayAccess
{
    protected static $instance;

    protected $data = [];

    protected $dataRows = [];

    protected $table_name = null;

    protected $return_array = false;

    protected $_where = '';

    protected $_group = '';

    protected $_having = '';

    protected $_order = '';

    protected $_limit = '';

    protected $_page = '';

    protected $_count = '';

    protected $sql = '';

    public function __construct() {
        if(empty($this->table_name)){
            $table_name = get_class($this);
            $table_name = substr($table_name,strripos($table_name,'\\')+1);
            $prefix = Config::get('database.prefix');
            $this->table_name = $prefix . strtolower($table_name);
        }
    }

    public static function find(){
        if(self::$instance===null){
            self::$instance = new static();
        }
        return self::$instance;
    }

    /**
     * 查询一条数据
     * @return $this
     */
    function detail(): Model
    {
        $db = Db::table($this->table_name);
        $row = $db->where($this->_where)->group($this->_group)->having($this->_having)->order($this->_order)->get();
        //$db->getFieldsInfo('Field')
        $this->data = $row;
        $this->sql = $db->getLastSql();

        /*$reflectionClass = new \ReflectionClass($this);
        $properties = $reflectionClass->getProperties(\ReflectionProperty::IS_PROTECTED);
        foreach ($properties as $property){
            $p = $property->getName();
            if(substr($p,0,1)==="_"){
                unset($this->$p);
            }
        }*/

        if($this->return_array){
            return $this->data;
        }else{
            return $this;
        }
    }

    /**
     * 查询多条数据
     * @return $this
     */
    function getAll(){
        $db = Db::table($this->table_name);

        if($this->_page){
            $db->page($this->_page,$this->_count);
        }

        $rows = $db->where($this->_where)->group($this->_group)->having($this->_having)->order($this->_order)->limit($this->_limit)->select();
        $this->dataRows = $rows;
        $this->sql = $db->getLastSql();

        if($this->return_array){
            return $this->dataRows;
        }else{
            $rowsArr = [];
            $reflectionClass = new \ReflectionClass($this);
            $properties = $reflectionClass->getProperties();

            foreach ($this->dataRows as $row){
                $tmpModel = new Model();

                foreach ($properties as $property){
                    $p = $property->getName();
                    $tmpModel->$p = $this->$p;
                }

                $tmpModel->data = $row;
                $tmpModel->table_name = $this->table_name;
                unset($tmpModel->dataRows);
                $rowsArr[] = $tmpModel;
            }

            return $rowsArr;
        }
    }

    /**
     * 条件
     * @param null $where
     * @return $this
     */
    function where($where=null){
        if(empty($where)){
            $this->_where = "";
        }else{
            $this->_where = $where;
        }

        return $this;
    }

    /**
     * group
     * @param null $group
     * @return $this
     */
    function group($group=null){
        if(empty($group)){
            $this->_group = "";
        }else{
            $this->_group = $group;
        }

        return $this;
    }

    /**
     * having
     * @param null $having
     * @return $this
     */
    function having($having=null){
        if(empty($having)){
            $this->_having = "";
        }else{
            $this->_having = $having;
        }

        return $this;
    }

    /**
     * order
     * @param null $order
     * @return $this
     */
    function order($order=null){
        if(empty($order)){
            $this->_order = "";
        }else{
            $this->_order = $order;
        }

        return $this;
    }

    /**
     * limit
     * @param null $limit
     * @return $this
     */
    function limit($limit=null){
        if(empty($limit)){
            $this->_limit = "";
        }else{
            $this->_limit = $limit;
        }

        return $this;
    }

    /**
     * limit
     * @param null $limit
     * @return $this
     */
    function page($page,$count=15){
        if(empty($page)){
            $this->_page = 0;
        }else{
            $this->_page = $page;
            $this->_count = $count;
        }

        return $this;
    }

    function toArray(){
        return $this->data;
    }

    function asArray(){
        $this->return_array = true;
        return $this;
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->data[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }

    function __get($name)
    {
        return isset($this->data[$name])?$this->data[$name]:null;
    }

    function __set($name,$value)
    {
        return $this->data[$name] = $value;
    }
}
